home *** CD-ROM | disk | FTP | other *** search
/ Computer Music Interactif…cial Edition 1999 Winter / cd 3.iso / mac / Mac / Shares / Midishare™1.68 / Development Tools / tutorial MidiShare TC6 / msTutorial.c next >
Encoding:
Text File  |  1994-03-08  |  25.4 KB  |  777 lines  |  [TEXT/KAHL]

  1. ///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  2. //===================================================================================
  3. //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  4. //
  5. //                                 MIDISHARE MINI TUTORIAL
  6. //
  7. //      This program is a small tutorial for MidiShare programming with THINK C 6.0. 
  8. //
  9. // HOW TO USE IT :
  10. //
  11. // 1) first of all MidiShare must be installed.If it is not installed, you need to copy
  12. // the file "MidiShare™ 1.68" into your system folder (actually the control panel folder) 
  13. // and reboot.
  14. //
  15. // 2) Then you need to copy the "MidiShare.h" file into your include folder.
  16. //
  17. // 3) Now you are ready for the tutorial. Update the project and run the program with 
  18. // the debugger option. Use the GO command to start the program and follow the instructions
  19. // displayed in the console window. Break points are installed in several points of the 
  20. // program in order for you to look at the code and understand how MidiShare works.
  21. //
  22. ///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  23. //===================================================================================
  24. //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
  25.  
  26.  
  27.  
  28. #include <MidiShare.h>
  29. #include <stdio.h>
  30.  
  31. long        ourRefNum;
  32. MidiSeqPtr    ourSequence;
  33. TFilter        ourFilter;
  34. long        stopFlag;
  35.  
  36.  
  37.  
  38.  
  39.  
  40. //===================================================================================
  41. // Welcome to the tutorial
  42. //===================================================================================
  43.  
  44. void welcome ()
  45. {
  46.     printf (" <<<< WELCOME TO THE MIDISHARE TUTORIAL >>>> \n\n");
  47.     DebugStr ("\p --> use the GO command to run the first test");
  48. }
  49.  
  50.  
  51.  
  52.  
  53. //===================================================================================
  54. // test 1 : Check if MidiShare is installed
  55. //===================================================================================
  56. // First of all, an application have to make sure that MidiShare is in memory. 
  57. // This checking is done thanks to the MidiShare function. The result is 1 if 
  58. // MidiShare is installed and 0 otherwise. Check the Console Window for the
  59. // result.
  60.  
  61. void test1 () 
  62. {
  63.     printf("\n\n <TEST 1 : Check if MidiShare is installed> \n");
  64.     DebugStr ("\p --> use the GO command to check if MidiShare is installed and go to the next test");
  65.     
  66.     printf("MidiShare installed  : %s\n", (MidiShare() ? "YES" : "NO") );
  67. }
  68.  
  69. // NOTE : Check the Console Window for the result.It must be 'YES'. If it is not, you must 
  70. // quit Think C, install MidiShare, and reboot.
  71.  
  72.  
  73.  
  74.  
  75.  
  76. //===================================================================================
  77. // test 2 : current version of MidiShare
  78. //===================================================================================
  79. // MidiGetVersion gives the version number of MidiShare. The result must be
  80. // 168 or greater.
  81.  
  82. void test2 ()
  83. {    
  84.     long     v;
  85.     
  86.     printf("\n\n<TEST 2> Get MidiShare version\n");
  87.     DebugStr ("\p --> use the GO command to get the MidiShare version and go to the next test");
  88.     
  89.     v = MidiGetVersion();
  90.      printf("MidiShare version : %ld.%ld\n", v / 100, v % 100);
  91. }                                  
  92.  
  93.  
  94.  
  95.  
  96. //===================================================================================
  97. // test 3 : how many client applications are running ?
  98. //===================================================================================
  99. // The MidiCountAppls gives the number of active Midi applications on. The result 
  100. // here will probably be 0. It means that no MidiShare client applications are running.
  101.  
  102. void test3 ()
  103. {
  104.     printf("\n\n<TEST 3> Count MidiShare client applications\n");
  105.     DebugStr ("\p --> use the GO command to count MidiShare client applications and go to the next test");
  106.  
  107.     printf("Count of MidiShare client applications : %hi\n", MidiCountAppls());
  108. }
  109.  
  110.  
  111.  
  112.  
  113. //===================================================================================
  114. // test 4 : register as a client application
  115. //===================================================================================
  116. // A Midi application need first to register as a client of MidiShare by calling MidiOpen.
  117. //
  118. // MidiOpen allows the recording of some information relative to the application 
  119. // context (its name, the value of the global data register, etc...), to allocate a 
  120. // reception FIFO and to attribute a unique reference number to the application. 
  121. // In counterpart to any MidiOpen call, the application must call the MidiClose 
  122. // function before leaving, by giving its reference number as an argument. 
  123. // MidiShare can thus be aware of the precise number of active Midi applications. 
  124. //
  125. // The result of MidiOpen is a reference number (>0) we need to keep in a global. 
  126. // If some errors occur the result is an error code (<0).
  127.  
  128. void test4 ()
  129. {
  130.     printf("\n\n<TEST 4> Register as a client application\n");
  131.     DebugStr ("\p --> use the GO command to register as a client application and go to the next test");
  132.  
  133.     ourRefNum = MidiOpen("\pThink C Tutorial");
  134.     if (ourRefNum > 0) 
  135.         printf("MidiOpen succeed. Our reference number is : %ld\n", ourRefNum);
  136.     else
  137.         printf("MidiOpen fail. The error code is : %ld\n", ourRefNum); 
  138. }
  139.  
  140.  
  141.  
  142.  
  143. //===================================================================================
  144. // test 5 : how many client applications are running now?
  145. //===================================================================================
  146. // Now lets check again for the number of MidiShare client applications on activity.
  147.  
  148. void test5 ()
  149. {
  150.     printf("\n\n<TEST 5> Count again MidiShare client applications \n");
  151.     DebugStr ("\p --> use the GO command to count again MidiShare client applications and go to the next test");
  152.  
  153.     printf("Count of MidiShare client applications : %hi\n", MidiCountAppls());
  154. }                                         
  155.  
  156. // The result is probably 2. Actually when the first client opens, a pseudo application 
  157. // with name "MidiShare" and reference number 0 is also started. You can think of it as 
  158. // the Midi drivers of MidiShare. For this reason we have a count of 2 client 
  159. // applications instead of 1. This pseudo application "MidiShare" cannot be closed
  160. // directly. It is closed automatically when the very last client application closes. 
  161.  
  162.  
  163.  
  164.  
  165. //===================================================================================
  166. // test 6 : list MidiShare client applications
  167. //===================================================================================
  168. // We are now going to list all the client applications on activity.
  169.  
  170. void listOfAppl ()
  171. {
  172.     long     i, ref;
  173.     long    n = MidiCountAppls();
  174.     
  175.     printf("List of MidiShare client applications\n");
  176.     printf("-------------------------------------\n");
  177.     for (i = 1; i<= n; i++) {
  178.         ref = MidiGetIndAppl(i);    // get the refnum form the order number
  179.         printf(" %2ld : reference number %2ld, name : '%#s' \n", i , ref, MidiGetName(ref));
  180.     }
  181.     printf("-------------------------------------\n\n");
  182. }
  183.  
  184. void test6 ()
  185. {
  186.     printf("\n\n<TEST 6> List every MidiShare client applications\n");
  187.     DebugStr ("\p --> use the GO command to list every MidiShare client applications and go to the next test");
  188.  
  189.     listOfAppl();
  190. }
  191.  
  192. // NOTE : The MidiGetIndAppl function allows to know the reference number of any 
  193. // application by giving its order number (a number between 1 and MidiCountAppls).
  194. // The MidiGetName function gives the name (the address of a Pascal string) of a client
  195. // application from its reference number. 
  196. //
  197. // In the console window the result will be :
  198. //
  199. // List of MidiShare client applications
  200. // -------------------------------------
  201. //   1 : reference number  0, name : 'MidiShare'
  202. //   2 : reference number  1, name : 'Think C Tutorial'
  203. // -------------------------------------
  204.  
  205. // NOTE : The reference number of the pseudo application "MidiShare" is always 0.
  206.  
  207.  
  208.  
  209.  
  210. //===================================================================================
  211. // test 7 : search for a client application with name "Think C Tutorial"
  212. //===================================================================================
  213. // Knowing an application name, it is possible to find its reference number using
  214. // the MidiGetNamedAppl function. If more than one client applications have the same
  215. // name the result is the reference number of the first one (the one with the smallest
  216. // reference number).
  217.  
  218. void test7 ()
  219. {
  220.     printf("\n\n<TEST 7> search the reference number of 'Think C Tutorial'\n");
  221.     DebugStr ("\p --> use the GO command to search the reference number of 'Think C Tutorial' and go to the next test");
  222.  
  223.     printf("Reference number of '%#s' : %d\n", "\pThink C Tutorial", MidiGetNamedAppl("\pThink C Tutorial"));
  224. }
  225.  
  226.  
  227.  
  228.  
  229. //===================================================================================
  230. // test 8 : search for a client application with name "XYZ"
  231. //===================================================================================
  232. // If we look for a non existant name the result is -4. This means that no application
  233. // with that name was found. Negative reference numbers are used as error codes.
  234.  
  235. void test8 ()
  236. {
  237.     printf("\n\n<TEST 8> search the reference number of 'XYZ'\n");
  238.     DebugStr ("\p --> use the GO command search the reference number of 'XYZ' and go to the next test");
  239.  
  240.     printf("Reference number of '%#s' : %d\n", "\pXYZ", MidiGetNamedAppl("\pXYZ"));
  241.     printf("A negative result means that the application was not found.\n");
  242. }
  243.  
  244.  
  245.  
  246.  
  247. //===================================================================================
  248. // test 9 : change the name of client application "Think C Tutorial" to "MidiShare Tutorial"
  249. //===================================================================================
  250. // MidiSetName allows to change the name of a client application.
  251.  
  252. void test9 ()
  253. {
  254.     printf("\n\n<TEST 9> change the name of client application 'Think C Tutorial' to 'MidiShare Tutorial'\n");
  255.     DebugStr ("\p --> use the GO command to change the name and go to the next test");
  256.  
  257.     MidiSetName(MidiGetNamedAppl("\pThink C Tutorial"), "\pMidiShare Tutorial");
  258.     listOfAppl ();
  259. }
  260.  
  261. // In the console window the result will be :
  262. // List of MidiShare client applications
  263. // -------------------------------------
  264. //   1 : reference number  0, name : 'MidiShare'
  265. //   2 : reference number  1, name : 'MidiShare Tutorial'
  266. // -------------------------------------
  267.  
  268.  
  269.  
  270.  
  271. //===================================================================================
  272. // test 10 : connect 'MidiShare Tutorial' to 'MidiShare'
  273. //===================================================================================
  274. // For an application to be able to transmit and receive events, it must first connect
  275. // to some source and destination applications. The MidiConnect function is used to 
  276. // connect or disconnect a source and a destination. The function takes 3 arguments :
  277. // the reference number of the source, the reference number of the destination and a
  278. // boolean (1 to connect and 0 to disconnect).
  279.  
  280. void test10 ()
  281. {
  282.     printf("\n\n<TEST 10> connect the output of 'MidiShare Tutorial' to 'MidiShare'\n");
  283.     DebugStr ("\p --> use the GO command to make the connection and go to the next test");
  284.  
  285.     MidiConnect(ourRefNum, 0, true);
  286. }
  287.  
  288. // Now we are able to send events to the pseudo application "MidiShare", i.e. to
  289. // external Midi devices.
  290.  
  291.  
  292.  
  293.  
  294. //===================================================================================
  295. // test 11 : test if 'MidiShare Tutorial' is connected to MidiShare
  296. //===================================================================================
  297. // We can test the connections using MidiIsConnected.
  298.  
  299. void test11 ()
  300. {
  301.     printf("\n\n<TEST 11> test a connection\n");
  302.     DebugStr ("\p --> use the GO command to test the connection and go to the next test");
  303.  
  304.     if (MidiIsConnected(ourRefNum, 0))
  305.         printf("We are connected to the MidiShare output driver\n");
  306.     else
  307.         printf("We are not connected\n");
  308. }
  309.  
  310.  
  311. //===================================================================================
  312. // test 12 : list the destinations of an application
  313. //===================================================================================
  314. // We can list all the destinations of an application by using MidiIsConnected for 
  315. // each possible destination
  316.  
  317. void listOfDest (long src)
  318. {
  319.     long     i, dst;
  320.     long    n = MidiCountAppls();
  321.     
  322.     printf("List of destinations of '%#s' \n", MidiGetName(src));
  323.     printf("-------------------------------------\n");
  324.     for (i = 1; i<= n; i++) {
  325.         dst = MidiGetIndAppl(i);    // get the refnum form the order number
  326.         if (MidiIsConnected(src, dst))
  327.             printf(" --> reference number %2ld, name : '%#s' \n", dst, MidiGetName(dst));
  328.     }
  329.     printf("-------------------------------------\n\n");
  330. }
  331.  
  332. void test12 ()
  333. {
  334.     printf("\n\n<TEST 12> list the destinations of our application\n");
  335.     DebugStr ("\p --> use the GO command to list the destinations of our application and go to the next test");
  336.  
  337.     listOfDest(ourRefNum);
  338. }
  339.  
  340.  
  341. //===================================================================================
  342. // test 13 : list the sources of an application
  343. //===================================================================================
  344. // We can list all the sources of an application by using MidiIsConnected for 
  345. // each possible source
  346.  
  347. void listOfSrc (long dst)
  348. {
  349.     long     i, src;
  350.     long    n = MidiCountAppls();
  351.     
  352.     printf("List of sources of '%#s' \n", MidiGetName(dst));
  353.     printf("-------------------------------------\n");
  354.     for (i = 1; i<= n; i++) {
  355.         src = MidiGetIndAppl(i);    // get the refnum form the order number
  356.         if (MidiIsConnected(src, dst))
  357.             printf(" <-- reference number %2ld, name : '%#s' \n", src, MidiGetName(src));
  358.     }
  359.     printf("-------------------------------------\n\n");
  360. }
  361.  
  362. void test13 ()
  363. {
  364.     printf("\n\n<TEST 13> list the sources of the MidiShare output driver\n");
  365.     DebugStr ("\p --> use the GO command to list the sources of the MidiShare output driver and go to the next test");
  366.  
  367.     listOfSrc(0);
  368. }
  369.  
  370.  
  371.  
  372.  
  373. //===================================================================================
  374. // test 14 : send a note with a pitch, a velocity and a duration in milliseconds
  375. //===================================================================================
  376. // We are now ready to send a note event. Be sure to have a Midi equipment connected
  377. // to the Modem port.
  378.  
  379. void sendNote(long pitch)
  380. {
  381.     MidiEvPtr e = MidiNewEv(typeNote);
  382.     
  383.     if (e) {
  384.         Chan(e) = 0;                // channels have numbers from 0 to 15
  385.         Port(e) = 0;                // port 0 is Modem port, port 1 is Printer port
  386.         MidiSetField(e, 0, pitch);    // the pitch
  387.         MidiSetField(e, 1, 80);        // the velocity
  388.         MidiSetField(e, 2, 1000);    // the duration in milliseconds
  389.         
  390.         MidiSendIm(ourRefNum, e);
  391.     }
  392. }
  393.  
  394. void test14 ()
  395. {
  396.     printf("\n\n<TEST 14> send a note\n");
  397.     DebugStr ("\p --> use the GO command to send a note and go to the next test");
  398.  
  399.     sendNote(60);
  400. }
  401.  
  402. // The note was sent to your Midi equipment. Actually two messages where sent, a keyOn
  403. // and a keyOn with velocity 0 after the duration of the note.
  404.  
  405. // IMPORTANT NOTE :
  406. // MidiShare includes its own memory manager to store events and sequences. MidiNewEv 
  407. // allocates the required memory to store the note event and returns a pointer to it. 
  408. // This space is automatically disposed by MidiShare when the event is sent. This means 
  409. // that once you have sent an event you MUST NOT use it anymore. In particular you 
  410. // MUST NOT send it a second time, free it or make a copy of it.
  411.  
  412.  
  413.  
  414.  
  415. //===================================================================================
  416. // test 15 : send multiple notes
  417. //===================================================================================
  418. // As we just said, once an event is sent it must not be used or accessed any more.
  419. // Here is an example of how to send several copies of the same event.
  420.  
  421. void SendMultipleNotes (long n, long pitch, long delay)
  422. {
  423.     long        i;
  424.     MidiEvPtr     e = MidiNewEv(typeNote);
  425.     long        dt = MidiGetTime();
  426.     
  427.     if (e) {
  428.         Chan(e) = 0;
  429.         Port(e) = 0;
  430.         MidiSetField(e, 0, pitch);        // the pitch
  431.         MidiSetField(e, 1, 80);            // the velocity
  432.         MidiSetField(e, 2, delay-1);    // the duration
  433.         
  434.         for (i=0; i<n; i++) MidiSendAt(ourRefNum, MidiCopyEv(e), dt + i*delay);
  435.         MidiFreeEv(e);
  436.     }
  437. }
  438.  
  439. void test15 ()
  440. {
  441.     printf("\n\n<TEST 15> send many notes in the future\n");
  442.     DebugStr ("\p --> use the GO command to send many notes in the future and go to the next test");
  443.  
  444.     SendMultipleNotes(10, 60, 250);
  445.     
  446.     printf("\n\n<TEST 15 bis> send more notes in the future\n");
  447.     DebugStr ("\p --> use the GO command to send more notes in the future and go to the next test");
  448.  
  449.     SendMultipleNotes(6, 60, 800);
  450.     SendMultipleNotes(8, 72, 600);
  451. }
  452.  
  453.  
  454.  
  455.  
  456. //===================================================================================
  457. // test 16 : send 'hello' lyric
  458. //===================================================================================
  459. // MidiShare defines several types of events. Some of them correspond to real Midi
  460. // messages, some others (like notes) are translated to Midi messages and some others
  461. // correspond to Midi File 1.0 data. Here is an example of sending Midi File Lyrics
  462. // data to another application. 
  463. //
  464. // <<<< For this test you need to launch 'msDisplay' application (in the 'MidiShare suite' folder) 
  465.  
  466.  
  467. void sendLyric(char* c)
  468. {
  469.     MidiEvPtr     e = MidiNewEv(typeLyric);
  470.     
  471.     if (e) {
  472.         Chan(e) = 0;                // channels have numbers from 0 to 15
  473.         Port(e) = 0;                // port 0 is Modem port, port 1 is Printer port
  474.         while (*c) MidiAddField(e, *c++);    // Fill the event with the string
  475.         
  476.         MidiSendIm(ourRefNum, e);
  477.     }
  478. }
  479.  
  480. void test16 ()
  481. {
  482.     printf("\n\n<TEST 16> send a Lyric to 'msDisplay'\n");
  483.     printf("YOU NEED TO LAUNCH 'msDisplay' FOR THIS TEST!!!\n");
  484.     DebugStr ("\p --> use the GO command to send a Lyric to 'msDisplay' and go to the next test");
  485.  
  486.     if (MidiGetNamedAppl ("\pmsDisplay") < 0) {
  487.         printf("You need to launch msDisplay for this test\n");
  488.     } else {
  489.         MidiConnect(0, MidiGetNamedAppl ("\pmsDisplay"), false);
  490.         MidiConnect(ourRefNum, MidiGetNamedAppl ("\pmsDisplay"), true);
  491.         sendLyric("Hello");
  492.     }
  493. }
  494. // msDisplay shows the 'Hello' message in its window
  495.  
  496.  
  497.  
  498.  
  499. //===================================================================================
  500. // test 17 : send a text event
  501. //===================================================================================
  502. // Here is a more general way to send Midi File textual events 
  503.  
  504.  
  505. void sendText(int aTextType, char* c)
  506. {
  507.     MidiEvPtr     e = MidiNewEv(aTextType);
  508.     
  509.     if (e) {
  510.         Chan(e) = 0;                // channels have numbers from 0 to 15
  511.         Port(e) = 0;                // port 0 is Modem port, port 1 is Printer port
  512.         while (*c) MidiAddField(e, *c++);    // Fill the event with the string
  513.         
  514.         MidiSendIm(ourRefNum, e);
  515.     }
  516. }
  517.  
  518. void test17 ()
  519. {
  520.     printf("\n\n<TEST 17> send other textual events\n");
  521.     DebugStr ("\p --> use the GO command to send other textual events to 'msDisplay' and go to the next test");
  522.  
  523.     sendText (typeText, "Hello");
  524.     sendText (typeCopyright, "Mozart");
  525.     sendText (typeSeqName, "Concerto");
  526.     sendText (typeInstrName, "Piano");
  527.     sendText (typeLyric, "Hiiiiiii");
  528.     sendText (typeMarker, "mark 1");
  529.     sendText (typeCuePoint, "Reverb here");
  530. }
  531.  
  532.  
  533.  
  534.  
  535. //===================================================================================
  536. // test 18 : send an SMPTE offset
  537. //===================================================================================
  538.  
  539. void sendSMPTEOffset (long format, long hours, long minutes, long seconds, long frames, long subframes)
  540. {
  541.     MidiEvPtr     e = MidiNewEv(typeSMPTEOffset);
  542.     
  543.     if (e) {
  544.         Chan(e) = 0;                // channels have numbers from 0 to 15
  545.         Port(e) = 0;                // port 0 is Modem port, port 1 is Printer port
  546.           MidiSetField(e, 0, format);        
  547.           MidiSetField(e, 1, hours);        
  548.           MidiSetField(e, 2, minutes);        
  549.           MidiSetField(e, 3, seconds);        
  550.           MidiSetField(e, 4, frames);        
  551.           MidiSetField(e, 5, subframes);    
  552.         
  553.         MidiSendIm(ourRefNum, e);
  554.     }
  555. }
  556.  
  557. void test18 ()
  558. {
  559.     printf("\n\n<TEST 18> send an SMPTE offset\n");
  560.     DebugStr ("\p --> use the GO command to send an SMPTE offset to 'msDisplay' and go to the next test");
  561.  
  562.     sendSMPTEOffset(1, 10, 24, 59, 12, 00);    
  563. }
  564.  
  565. //===================================================================================
  566. // test 19 : thru incomming events
  567. //===================================================================================
  568. // We are now going to see how to receive events. Every client application have a 
  569. // reception fifo where incoming events are stored. Applications can be informed
  570. // in real-time of incoming events using a receive alarm. The receive alarm is called
  571. // at interrupt level when new events are received. In this example, the receive alarm
  572. // just thru the events
  573. //
  574. // WARNING : don't set breakpoints in the 'thru' routine!!!!. It is called
  575. // at interrupt level
  576.  
  577. pascal void thru (short aRefNum)
  578. {
  579.     MidiEvPtr e;
  580.     
  581.     while (e = MidiGetEv(aRefNum)) MidiSend(aRefNum, e);
  582. }
  583.  
  584. void test19 ()
  585. {
  586.     printf("\n\n<TEST 19> thru incomming events\n");
  587.     DebugStr ("\p --> use the GO command to start thruing incomming events");
  588.  
  589.     MidiFlushEvs(ourRefNum);
  590.     MidiSetRcvAlarm(ourRefNum, thru);
  591.     MidiConnect(0, ourRefNum, true);
  592.     MidiConnect(ourRefNum, 0, true);
  593.  
  594.     printf("Now play on the Midi keyboard\n");
  595.     DebugStr ("\p --> use the GO command to stop thruing incomming events and go to the next test");
  596.  
  597.     MidiConnect(0, ourRefNum, false);
  598.     MidiSetRcvAlarm(ourRefNum, 0);
  599. }
  600.  
  601. //===================================================================================
  602. // test 20 : delay and transpose incoming notes
  603. //===================================================================================
  604. // In this example, note, keyOn and keyOff events are transposed and sent with a delay. 
  605. // Other received events are deleted. 
  606.  
  607. pascal void transposeAndDelay (short aRefNum)
  608. {
  609.     MidiEvPtr e;
  610.     
  611.     while (e = MidiGetEv(aRefNum)) {
  612.         switch (EvType(e)) {
  613.             case typeNote:
  614.             case typeKeyOn:
  615.             case typeKeyOff:
  616.                 MidiSetField(e, 0, 7 + MidiGetField(e,0));    // transpose pitch + 7
  617.                 Date(e) += 1000;                            // delay 1000 ms
  618.                 MidiSend(aRefNum, e);
  619.                 break;
  620.             default:
  621.                 MidiFreeEv(e);
  622.         }
  623.     }
  624. }
  625.  
  626. void test20 ()
  627. {
  628.     printf("\n\n<TEST 20> transpose and delay in real-time\n");
  629.     DebugStr ("\p --> use the GO command to start transposing incomming events");
  630.  
  631.     MidiFlushEvs(ourRefNum);
  632.     MidiSetRcvAlarm(ourRefNum, transposeAndDelay);
  633.     MidiConnect(0, ourRefNum, true);
  634.     MidiConnect(ourRefNum, 0, true);
  635.  
  636.     printf("Now play on the Midi keyboard, notes are transposed and delayed\n");
  637.     DebugStr ("\p --> use the GO command to stop transposing events and go to the next test");
  638.  
  639.     MidiConnect(0, ourRefNum, false);
  640.     MidiSetRcvAlarm(ourRefNum, 0);
  641. }
  642.  
  643. //===================================================================================
  644. // test 21 : record and playback a sequence
  645. //===================================================================================
  646. // We are now going to see how to record incoming events in a sequence and play back
  647. // this sequence. To playback we use a task, a function called in the future.
  648.  
  649. void InstallFilter (short aRefNum, FilterPtr aFilter)
  650. {
  651.     short i;
  652.  
  653.     for (i = 0; i<256; i++)                            /* initialise the filter :            */
  654.     {                                         
  655.         AcceptBit(aFilter->evType,i);                /*  accept every MidiShare events    */
  656.         AcceptBit(aFilter->port,i);                    /*  on every Midi ports                */
  657.     }
  658.                                             
  659.     for (i = 0; i<16; i++)
  660.         AcceptBit(aFilter->channel,i);                /*  on every Midi channels            */
  661.         
  662.     RejectBit(aFilter->evType, typeActiveSens);        /* reject active sensing events        */
  663.         
  664.     MidiSetFilter( aRefNum, aFilter );               /* install the filter                */
  665. }
  666.  
  667. pascal void record (short aRefNum)
  668. {
  669.     MidiEvPtr e;
  670.     
  671.     while (e = MidiGetEv(aRefNum)) {
  672.         MidiSendIm(aRefNum, MidiCopyEv(e)); // Remove this line if you don't want to thru events
  673.         MidiAddSeq(ourSequence,e);
  674.     }
  675. }
  676.  
  677. pascal void play (long time, short refnum, long nextEv, long unused1, long unused2)
  678. {
  679.     MidiEvPtr     e = (MidiEvPtr) nextEv;
  680.     long        date = Date(e);
  681.     
  682.     if (!stopFlag) {
  683.         while (e && Date(e) == date) {            // play all the events at the same date
  684.             MidiSendIm(refnum, MidiCopyEv(e));
  685.             e = e->link;
  686.         }
  687.         if (e)                                     // still events to play?
  688.             MidiCall(play, time + Date(e) - date, refnum, (long)e, 0, 0);
  689.     }
  690. }
  691.  
  692. long size (MidiSeqPtr s)
  693. {
  694.     long        n;
  695.     MidiEvPtr    e;
  696.     
  697.     for (n = 0, e = FirstEv(s); e; e = e->link) n++;
  698.     return n;
  699. }
  700.  
  701. void test21 ()
  702. {
  703.     long    n;
  704.     
  705.     printf("\n\n<TEST 21> record and playback a sequence\n");
  706.     DebugStr ("\p --> use the GO command to start recording");
  707.  
  708.     ourSequence = MidiNewSeq();
  709.     InstallFilter(ourRefNum, &ourFilter);
  710.     MidiFlushEvs(ourRefNum);
  711.     MidiSetRcvAlarm(ourRefNum, record);
  712.     MidiConnect(0, ourRefNum, true);
  713.     MidiConnect(ourRefNum, 0, true);
  714.     
  715.     printf("Now play on the Midi keyboard, every thing is recorded\n");
  716.     DebugStr ("\p --> use the GO command to stop recording");
  717.  
  718.     MidiConnect(0, ourRefNum, false);
  719.     MidiSetRcvAlarm(ourRefNum, 0);
  720.     
  721.     printf (" %ld events where recorded\n", size(ourSequence));
  722.  
  723.     DebugStr ("\p --> use the GO command to play back the sequence");
  724.  
  725.     stopFlag = 0;
  726.     if (FirstEv(ourSequence)) {
  727.         MidiCall(play, MidiGetTime(), ourRefNum, (long) FirstEv(ourSequence), 0, 0);
  728.     }
  729.     
  730.     printf("Now playing the sequence\n");
  731.     DebugStr ("\p --> use the GO command to stop play back and go to the next test");
  732.     
  733.     stopFlag = 1;
  734.     MidiFreeSeq(ourSequence);
  735. }
  736.     
  737.  
  738. //===================================================================================
  739. // test 22 : close MidiShare Session
  740. //===================================================================================
  741.  
  742. void test22 ()
  743. {
  744.     printf("\n\n<TEST 22> close the MidiShare session\n");
  745.     DebugStr ("\p --> use the GO command to end the session and exit the tutorial");
  746.  
  747.     MidiClose(ourRefNum);
  748.     printf("THE TUTORIAL IS NOW FINISHED!\n");
  749. }
  750.  
  751. void main()
  752. {
  753.     welcome();
  754.     test1();
  755.     test2();
  756.      test3();
  757.      test4();
  758.      test5();
  759.      test6();
  760.      test7();
  761.      test8();
  762.      test9();
  763.      test10();
  764.      test11();
  765.      test12();
  766.      test13();
  767.      test14();
  768.      test15();
  769.      test16();
  770.      test17();
  771.      test18();
  772.      test19();
  773.      test20();
  774.      test21();
  775.      
  776.      test22();
  777. }